#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
#   Measurement script for collecting real data
#  
#   Author: Tim
#


import threading
import serial
import sys
import pickle

from Keymap import protocol, keymap


class Test(threading.Thread):
    def __init__(self, port, baud, filename):
        threading.Thread.__init__(self)
        # test constants
        self.NUM_POINTS = 1
        self.ANGLES_PER_POINT = 35
        self.SAMPLES_PER_ANGLE = 10
        self.RECV_POS = 1
        self.SPECTRUM = 180
        self.ROWS = 1
        self.COLUMNS = 1
        
        # test variables
        self.point_counter = 0
        self.angle_counter = 0
        self.sample_counter = 0

        # the list where to store the values
        self.values = []
        
        # last received symbol
        self.last_symbol = ""
        self.protocol = ""
        
        # filename where to store the data
        self.filename = filename
        
        self.running = True
        self.port = port
        self.baud = baud
        self.ser = serial.Serial(self.port, self.baud)
        
        # init the value list
        self.init()
        
    def stop(self):
        self.running = False
        
    def init(self):
        # create list of dictionaries
        for i in range(0, self.NUM_POINTS):
            self.values.append({})
            for j in range(0, self.ANGLES_PER_POINT):
                self.values[i][j] = 0
        
    def write(self):
        # filename: name_samples_spectrum_rows_columns_recvpos
        # write binary
        f = open(self.filename+"_"+str(self.SAMPLES_PER_ANGLE)+"_"+str(self.SPECTRUM)+"_"+str(self.ROWS)+"_"+str(self.COLUMNS)+"_"+str(self.RECV_POS), "wb")
        pickle.dump(self.values, f)
        f.close()  
        # write text
        f = open(self.filename+"_"+str(self.SAMPLES_PER_ANGLE)+"_"+str(self.SPECTRUM)+"_"+str(self.ROWS)+"_"+str(self.COLUMNS)+"_"+str(self.RECV_POS)+".txt", "w")  
        f.write(str(self.values))
        f.close()
        
        
    def next(self):
        # save sample counter
        self.values[self.point_counter][self.angle_counter] = self.sample_counter
        # next angle
        if self.angle_counter == (self.ANGLES_PER_POINT-1):
            if self.point_counter == (self.NUM_POINTS-1):
                print "End of Experiment..."
                self.write()
                self.stop()
            else:
                self.point_counter += 1
                self.angle_counter = 0
        else:
            self.angle_counter += 1
        self.sample_counter = 0
        self.last_symbol = ""
        print "Point "+str(self.point_counter)+", Angle "+str(self.angle_counter)
        
    def run(self):
        
        print "Start Test Scenario..."
        print "Points:  "+str(self.NUM_POINTS)
        print "Angles:  "+str(self.ANGLES_PER_POINT)
        print "Samples: "+str(self.SAMPLES_PER_ANGLE)
        print "Point "+str(self.point_counter)+", Angle "+str(self.angle_counter)
        
        while self.running:
            
            line = str(self.ser.readline())
            if line.find(":") != -1:
            
                keyevent = line.split(":")
                self.protocol = keyevent[0]
                address = keyevent[1]
                command = keyevent[2]
                flag = keyevent[3][0]
                
                # ignore 'hold' flag
                if flag == "1":
                    continue
                
                new_symbol = ""
                if self.protocol in keymap.keys():
                    # keymap known for protocol
                    new_symbol = keymap.get(self.protocol).get(command)
                    # drop duds
                    if new_symbol == None:
                        print "##################### DUD #########################"
                        continue
                else:
                    # unknown keymap
                    new_symbol = command
                    
                # check for angle change
                if (self.last_symbol != "") and (self.last_symbol != new_symbol):

                    self.last_symbol = new_symbol
                
                    # write number of received samples to the list
                    self.values[self.point_counter][self.angle_counter] = self.sample_counter
                    self.write()
                    
                    # reset sample counter, 1 because we just received a symbol
                    self.sample_counter = 1
                    
                    # check for point change
                    if self.angle_counter == (self.ANGLES_PER_POINT-1):
                        # check for end of experiment
                        if self.point_counter == (self.NUM_POINTS-1):
                            print "End of experiment..."
                            self.write()
                            self.stop()
                        else:
                            self.angle_counter = 0
                            self.point_counter += 1
                            print "Point "+str(self.point_counter)+", Angle "+str(self.angle_counter)
                            print new_symbol+" received"
                    else:
                        self.angle_counter += 1
                        print "Point "+str(self.point_counter)+", Angle "+str(self.angle_counter)
                        print new_symbol+" received"
                else:
                    self.sample_counter += 1
                    self.last_symbol = new_symbol
                    print new_symbol+" received"

# argumenting          
filename = ""
if len(sys.argv) != 2:
    print "Usage: ./Test.py filename"
    sys.exit(1)
else:            
    filename = sys.argv[1]

# start the test             
test = Test("/dev/ttyACM0", 115200, filename)
test.start()

# wait for commands on keyboard
while True:
    key = sys.stdin.read(1)
    if key == "q":
        test.stop()
        sys.exit(0)   
    elif key == "n":
        test.next()
    else:
        pass
        
    
